
struct fibril;
typedef struct G G;

struct G
{
	G* free_link;
	G* all_link;
	void*	entry;       // initial function
	void*	param;		// passed parameter on wakeup
	Defer*	defer;
	Panic*	panic;

	// Buffer for diverting output.
	byte*	writebuf;
	int32	writenbuf;

	int32    goid;       // id of this goroutine
	uintptr  gopc;       // pc of go statement that created this goroutine
	struct fibril *fib;  // a fibril that runs this goroutine

	int16	status;

	// For defer and panic handling.


	// Exception handling stuff.
	void*	exception;	// current exception being thrown
	bool	is_foreign;	// whether current exception from other language
	bool	ispanic;
};

enum
{
	Grunning,
	Gwaiting,
	Gdead,
};

// Number of running goroutines.
int32	runtime_gcount(void) __asm__("runtime.NumGoroutine");

// Currently running goroutine.
G*   runtime_g(void);

// Switch to another goroutine and possibly enqueue the calling goroutine.
void runtime_gosched(void);

// Enqueue a goroutine.
void runtime_ready(G*);

// Debugging.

G *runtime_allg(void);

// Must be called from fibrils initialized elsewhere before any Go code.
_Bool runtime_fibril_setup(void);
// Must be called from fibrils in which FibrilSetup() was called, after any Go code.
void runtime_fibril_teardown(void);


G* runtime_grun(void (*fn)(void*), uintptr retaddr, void* arg, uintptr stack_size);

G* __go_go(void (*pfn)(void*), void*);

uintptr runtime_gstack_start(G *g);
uintptr runtime_gstack_last(G *g);

void runtime_LockOSThread(void) __asm__("runtime.LockOSThread");
void runtime_UnlockOSThread(void) __asm__("runtime.UnlockOSThread");
bool runtime_lockedOSThread(void);

void runtime_lock_world(void);
bool runtime_stop_world(void);
void runtime_unlock_world(void);
void runtime_start_world(void);

/*

//void	runtime_schedinit(void);

void	runtime_goexit(void);

int32	runtime_gomaxprocsfunc(int32 n);

void runtime_enable_multithread(void);

*/
